"use strict";
const FLog = require("./FLog");
const FError = require("./FError");

function handleError(err) {
  if (!err || err.statusCode) return err;
  switch (err.code || err.message || err) {
    case "STATUS_PENDING":
      break;
    case "invalide encoding":
      err = FError.InvalidEncoding("invalid encoding");
      err.statusCode = 403;
      break;
    case 11000:
      err = FError.DuplicateKey("mongo duplicate key error");
      err.statusCode = 403;
      break;
    case "jwt expired":
      err = FError.TokenExpired("token has expired");
      err.statusCode = 401;
      break;
    case "ETIMEDOUT":
      err = FError.ConnectTimeOut("connect time out");
      err.statusCode = 502;
      break;
    default:
      err = err instanceof FError ? err : FError.RequestError();
      err.statusCode =
        err instanceof FError && err.statusCode ? err.statusCode : 500;
      break;
  }
  return err;
}

function handleStatus(method, body) {
  let status = 200;
  switch (method) {
    case "GET":
    case "get":
      status = 200;
      break;
    case "POST":
    case "post":
      status = 201;
      break;
    case "PUT":
    case "put":
    case "DELETE":
    case "delete":
      status = 204;
      break;
    default:
      status = 200;
      break;
  }
  if (body) status = 200;
  return status;
}

/**
 * @function layout
 * @param {module: FError} err 错误类型对象或null
 * @param {Object} ctx
 * @param {Object} body 返回参数或null
 */
exports.layout = (err, ctx, body) => {
  /**系统异常 */
  err = handleError(err);
  /**定义的错误类型和协议码 */
  const method = ctx.method;
  const status = handleStatus(method, body);
  const { errorCode, errorMsg, statusCode } = err
    ? err
    : { errorCode: 0, errorMsg: null, statusCode: status };
  /**返回参数 */
  ctx.status = statusCode;
  ctx.body = {
    errNo: errorCode,
    msg: errorMsg,
    item: body
  };
};
